package com.dingreading.cloud.soms.controller;

import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.data.RichTextStringData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.dingreading.cloud.common.base.R;
import com.dingreading.cloud.common.dto.LoginDataDto;
import com.dingreading.cloud.common.dto.StaffRoleDto;
import com.dingreading.cloud.common.util.*;
import com.dingreading.cloud.common.util.excel.ExcelHandler;
import com.dingreading.cloud.common.util.excel.RowBean;
import com.dingreading.cloud.soms.dto.*;
import com.dingreading.cloud.soms.dto.vo.LessonBillVO;
import com.dingreading.cloud.soms.dto.vo.LessonVO;
import com.dingreading.cloud.soms.entity.*;
import com.dingreading.cloud.soms.service.*;
import com.dingreading.cloud.soms.util.*;
import com.google.common.collect.Lists;
import com.mybatisflex.core.paginate.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/front/caScheduleLesson/v2")
@Api(tags = "门店-活动记录管理V2")
public class FrontCaScheduleLessonControllerV2 {

    @Resource
    protected CaScheduleService scheduleService;
    @Resource
    protected CaScheduleLessonService scheduleLessonService;
    @Resource
    protected CaTeacherService teacherService;
    @Resource
    protected CaClassMemberService classMemberService;
    @Resource
    protected CaCallNamesService callNameService;
    @Resource
    protected CaClassService classService;
    @Resource
    protected CmservicesService cmservicesService;
    @Resource
    protected MembersService membersService;
    @Resource
    protected MemberFollowService memberFollowService;
    @Resource
    protected StaffRolesService staffRolesService;
    @Resource
    protected StoreProjectsService storeProjectsService;
    @Resource
    protected StaffService staffService;
    @Resource
    protected WxTemplateUtil wxTemplateUtil;
    @Resource
    private StoreFunctionService storeFunctionService;
    @Resource
    private CaClassroomsService caClassroomsService;


    @ApiOperation(value = "分页列表")
    @PostMapping(value = "/pageList")
    public R<Object> pageList(
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "分页公共类") PageUtil pageUtil,
            @ApiParam(value = "活动表uid") @RequestParam(value = "scheduleUid", required = false) String scheduleUid,
            @ApiParam(value = "活动uid") @RequestParam(value = "lessonUid", required = false) String lessonUid,
            @ApiParam(value = "社团id") @RequestParam(value = "classId", required = false) Long classId,
            @ApiParam(value = "社团名称") @RequestParam(value = "className", required = false) String className,
            @ApiParam(value = "活动室id") @RequestParam(value = "roomId", required = false) Long roomId,
            @ApiParam(value = "教师username") @RequestParam(value = "username", required = false) String username,
            @ApiParam(value = "活动服务uid") @RequestParam(value = "projectUid", required = false) String projectUid,
            @ApiParam(value = "活动状态 -1.已取消 0.未进行 1.已进行 2.已完成") @RequestParam(value = "status", required = false) Integer status,
            @ApiParam(value = "活动开始日期") @RequestParam(value = "beginDate", required = false) String beginDate,
            @ApiParam(value = "活动结束日期") @RequestParam(value = "endDate", required = false) String endDate
    ) {
        Page<CaScheduleLessonDto> page = scheduleLessonService.pageListV3(
                pageUtil, corpUid, storeUid, null, status, scheduleUid, lessonUid, classId, className, roomId,
                username, projectUid, beginDate, endDate
        );

        long total = page.getTotalRow();
        List<CaScheduleLessonDto> list = page.getRecords();

        if (CollectionUtils.isNotEmpty(list)) {
            List<String> scheduledUids = list.stream().map(CaScheduleLessonDto::getScheduleUid).distinct().collect(Collectors.toList());
            List<CaTeacherDto> teachers = teacherService.getTeachersByScheduleUids(storeUid, scheduledUids, 1);
            // 获取导读
            ScheduleUtil.listSetTeachers(list, teachers);
        }

        PageBeanDto data = new PageBeanDto();
        data.setTotal(total);
        data.setList(list);
        return R.ok(data);
    }

    @ApiOperation(value = "我的活动")
    @PostMapping(value = "/myPageList")
    public R<Object> myPageList(
            HttpServletRequest request,
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "分页公共类") PageUtil pageUtil,
            @ApiParam(value = "社团id") @RequestParam(value = "classId", required = false) Long classId,
            @ApiParam(value = "社团名称") @RequestParam(value = "className", required = false) String className,
            @ApiParam(value = "活动室id") @RequestParam(value = "roomId", required = false) Long roomId,
            @ApiParam(value = "活动服务uid") @RequestParam(value = "projectUid", required = false) String projectUid,
            @ApiParam(value = "活动状态 0.未活动 1.已活动 2.已完成") @RequestParam(value = "status", required = false) Integer status,
            @ApiParam(value = "活动开始日期") @RequestParam(value = "beginDate", required = false) String beginDate,
            @ApiParam(value = "活动结束日期") @RequestParam(value = "endDate", required = false) String endDate
    ) {
        // 获取员工信息
        R<Object> r = LoginInfoUtil.getLoginDto(request);
        if (R.isError(r)) return r;
        LoginDataDto loginDto = (LoginDataDto) r.getData();
        String username = loginDto.getUsername();

        Page<CaScheduleLessonDto> page = scheduleLessonService.pageListV3(pageUtil, corpUid, null, null, status,
                null, null, classId, className, roomId, username, projectUid, beginDate, endDate);

        long total = page.getTotalRow();
        List<CaScheduleLessonDto> list = page.getRecords();

        if (CollectionUtils.isNotEmpty(list)) {
            List<String> scheduledUids = list.stream().map(CaScheduleLessonDto::getScheduleUid).distinct().collect(Collectors.toList());
            List<CaTeacherDto> teachers = teacherService.getTeachersByScheduleUids(storeUid, scheduledUids, 1);
            // 获取导读
            ScheduleUtil.listSetTeachers(list, teachers);
        }

        PageBeanDto data = new PageBeanDto();
        data.setTotal(total);
        data.setList(list);
        return R.ok(data);
    }

    private final String[] localWeekDays = {"周一", "周二", "周三", "周四", "周五", "周六", "周日"};

    @ApiOperation(value = "活动日历")
    @PostMapping(value = "/calendarList")
    public R<Object> calendarList(
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "社团id") @RequestParam(value = "classId", required = false) Long classId,
            @ApiParam(value = "活动室id") @RequestParam(value = "roomId", required = false) Long roomId,
            @ApiParam(value = "活动服务uid") @RequestParam(value = "projectUid", required = false) String projectUid,
            @ApiParam(value = "教师username") @RequestParam(value = "username", required = false) String username,
            @ApiParam(value = "活动状态 0.未活动 1.已活动 2.已完成") @RequestParam(value = "status", required = false) Integer status,
            @ApiParam(value = "活动开始日期") @RequestParam(value = "beginDate", required = false) String beginDate,
            @ApiParam(value = "活动结束日期") @RequestParam(value = "endDate", required = false) String endDate
    ) throws Exception {
        if (StringUtils.isBlank(beginDate) || StringUtils.isBlank(endDate))
            return R.fail("请选择开始日期和结束日期");

        // 计算出2个日期间隔中的日期
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate startLocal = LocalDate.parse(beginDate, df);
        LocalDate endLocal = LocalDate.parse(endDate, df);
        JSONArray dateWeekList = DateUtil.collectLocalDatesAndWeek(startLocal, endLocal);

        List<CaScheduleLessonDto> list = scheduleLessonService.calendarListV3(corpUid, storeUid, null, status,
                classId, roomId, username, projectUid, beginDate, endDate);
        // 按活动日期分类
        LinkedHashMap<String, List<CaScheduleLessonDto>> teachDateMap = new LinkedHashMap<>();
        if (CollectionUtils.isNotEmpty(list))
            teachDateMap = list.stream().collect(Collectors.groupingBy(CaScheduleLessonDto::getTeachDate, LinkedHashMap::new, Collectors.toList()));

        JSONArray array = new JSONArray();
        for (int i = 0; i < dateWeekList.size(); i++) {
            JSONObject dateObj = dateWeekList.getJSONObject(i);
            String date = dateObj.getString("date");
            int week = dateObj.getIntValue("week");
            dateObj.put("weekName", localWeekDays[week - 1]);

            List<CaScheduleLessonDto> lessonList = teachDateMap.get(date);
            dateObj.put("list", lessonList);
            array.add(dateObj);
        }
        return R.ok(array);
    }

    @ApiOperation(value = "根据活动id获取活动详情及主讲导读")
    @PostMapping(value = "/getBean", produces = "application/json; charset=UTF-8")
    public R<Object> getBean(
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "活动uid") @RequestParam(value = "lessonUid") String lessonUid
    ) {
        CaScheduleLessonDto data = scheduleLessonService.getLessonDto(storeUid, lessonUid);
        // 设置教师
        if (null != data) {
            List<CaTeacherDto> teachers = teacherService.getTeachers(data.getStoreUid(), data.getScheduleUid(), 1);
            ScheduleUtil.objSetTeachers(data, teachers);
        }
        return R.ok(data);
    }

    @Transactional(rollbackFor = DescribeException.class)
    @ApiOperation(value = "编辑活动信息")
    @PostMapping(value = "/editBean", produces = "application/json; charset=UTF-8")
    public R<Object> editBean(
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "活动uid") @RequestParam(value = "lessonUid") String lessonUid,
            @ApiParam(value = "活动室id") @RequestParam(value = "roomId") Long roomId,
            @ApiParam(value = "活动室名称") @RequestParam(value = "roomName") String roomName,
            @ApiParam(value = "导读json {teacherType:0,staffUid:'',username:'',fullName:'',nickName:'',pubPhone:'',priPhone:''}")
            @RequestParam(value = "teacherJson") String teacherJson,
            @ApiParam(value = "活动内容") @RequestParam(value = "content", required = false) String content,
            @ApiParam(value = "备注") @RequestParam(value = "remark", required = false) String remark
    ) {
        CaScheduleLesson data = scheduleLessonService.getLessonInfo(storeUid, lessonUid);
        if (null == data) return R.fail("活动获取失败");
        if (data.getStatus().equals(-1)) return R.fail("活动已取消，不能操作");
        if (data.getStatus().equals(1)) return R.fail("活动已点名，不能操作");
        if (data.getStatus().equals(2)) return R.fail("活动已完成，不能操作");
        if (null == roomId) return R.fail("没有设置活动室，不能操作");
        if (StringUtils.isBlank(teacherJson)) return R.fail("没有设置主讲导读，不能操作");

        List<CaTeacher> teacherList = JSONArray.parseArray(teacherJson, CaTeacher.class);
        List<String> usernameList = new ArrayList<>();
        // 主讲导读username
        String topTeacherUid = "";
        // 主讲导读名
        String topTeacherName = "";
        for (CaTeacher teacher : teacherList) {
            usernameList.add(teacher.getUsername());
            if (StringUtils.isBlank(teacher.getStaffUid()))
                return R.fail("导读标识传递错误导读：" + teacher.getUsername());

            // 设置主讲导读
            if (teacher.getTeacherType().equals(1)) {
                topTeacherUid = teacher.getUsername();
                topTeacherName = teacher.getFullName();
            }
        }
        if (StringUtils.isBlank(topTeacherUid) || StringUtils.isBlank(topTeacherName))
            return R.fail("没有设置主讲导读");

        String dataStoreUid = data.getStoreUid();
        String scheduleUid = data.getScheduleUid();
        // 活动的教师username集合
        String usernames = "," + String.join(",", usernameList) + ",";

        CaClassrooms caClassrooms = caClassroomsService.getBean(storeUid, roomId);
        if (caClassrooms == null)
            return R.fail("未查询到教室");

        // 删除活动的教师
        teacherService.dropTeacherByLessonUid(dataStoreUid, scheduleUid, lessonUid);
        // 创建活动的导读
        ScheduleUtil.newTeachers(teacherList, corpUid, dataStoreUid, scheduleUid, lessonUid, staffUid, staffName);
        teacherService.saveOrUpdateBatch(teacherList);

        data.setRoomId(roomId);
        data.setRoomUid(caClassrooms.getUid());
        data.setRoomName(roomName);
        data.setContent(content);
        data.setRemark(remark);
        data.setLastStaffUid(staffUid);
        data.setLastStaffName(staffName);
        // 更新活动的主讲导读相关数据
        data.setTeacherUid(topTeacherUid);
        data.setTeacherName(topTeacherName);
        data.setUsernames(usernames);
        scheduleLessonService.saveOrUpdate(data);
        return R.ok();
    }

    @ApiOperation(value = "删除活动")
    @PostMapping(value = "/dropBean", produces = "application/json; charset=UTF-8")
    public R<Object> dropBean(
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "活动uid") @RequestParam(value = "lessonUid") String lessonUid
    ) {
        CaScheduleLesson lesson = scheduleLessonService.getLessonInfo(storeUid, lessonUid);
        if (null == lesson)
            return R.fail("活动获取失败");
        if (lesson.getStatus() > 0)
            return R.fail("活动已开始或已完成，不能删除");

        String lessonStoreUid = lesson.getStoreUid();
        String scheduleUid = lesson.getScheduleUid();

        long l = scheduleLessonService.dropBean(lessonStoreUid, lessonUid);
        if (l <= 0)
            return R.failDel();
        // 删除主讲导读
        teacherService.dropTeacherByLessonUid(lessonStoreUid, scheduleUid, lessonUid);

        // 删除点名记录
        callNameService.dropBean(lessonStoreUid, lessonUid, null);

        // 更新活动表的活动数量
        scheduleService.updateLessonNum(lessonStoreUid, scheduleUid);

        return R.ok();
    }

    @ApiOperation(value = "取消活动日程")
    @PostMapping(value = "/setCancel", produces = "application/json; charset=UTF-8")
    public R<Object> setCancel(
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "活动uid") @RequestParam(value = "lessonUid") String lessonUid
    ) {
        CaScheduleLesson lesson = scheduleLessonService.getLessonInfo(storeUid, lessonUid);
        if (null == lesson) return R.fail("活动获取失败");
        if (lesson.getStatus() > 0) return R.fail("活动已开始或已完成，不能取消");

        // 活动设置为已取消
        scheduleLessonService.setCancel(corpUid, lessonUid, staffUid, staffName);
        // 点名记录设置为已取消
        callNameService.setCancel(corpUid, lessonUid, staffUid, staffName);
        return R.ok();
    }

    @ApiOperation(value = "根据活动id集合获取活动列表及主讲导读")
    @PostMapping(value = "/getLessonsByUids", produces = "application/json; charset=UTF-8")
    public R<Object> getLessonsByUids(
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "活动uid集合") @RequestParam(value = "lessonUids") List<String> lessonUids
    ) {
        List<CaScheduleLessonDto> list = scheduleLessonService.getLessonByUids(storeUid, lessonUids);

        if (CollectionUtils.isNotEmpty(list)) {
            List<String> scheduledUids = list.stream().map(CaScheduleLessonDto::getScheduleUid).distinct().collect(Collectors.toList());
            List<CaTeacherDto> teachers = teacherService.getTeachersByScheduleUids(null, scheduledUids, 1);
            // 获取导读
            ScheduleUtil.listSetTeachers(list, teachers);
        }

        return R.ok(list);
    }

    @ApiOperation(value = "获取可插班的社团")
    @PostMapping(value = "/getInsertClass", produces = "application/json; charset=UTF-8")
    public R<Object> getInsertClass(
            HttpServletRequest request,
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "分页公共类") PageUtil pageUtil,
            @ApiParam(value = "社团名称/会员姓名") @RequestParam(value = "keyword", required = false) String keyword,
            @ApiParam(value = "活动uid") @RequestParam(value = "lessonUid", required = false) String lessonUid
    ) throws Exception {
        // 获取员工信息
        R<Object> r = LoginInfoUtil.getLoginDto(request);
        if (R.isError(r)) return r;
        LoginDataDto loginDto = (LoginDataDto) r.getData();
        String username = loginDto.getUsername();

        if (StringUtils.isNotBlank(keyword) && keyword.length() < 2)
            return R.fail("查询关键字至少填写2位");

        CaScheduleLesson lesson = scheduleLessonService.getLessonInfo(storeUid, lessonUid);
        if (null == lesson) return R.fail("活动获取失败");
        if (lesson.getStatus().equals(-1))
            return R.fail("活动已取消，不能操作");
        if (lesson.getStatus().equals(2))
            return R.fail("活动已结束，不能操作");

//        Date teachDate = DateUtil.parseDateFromStr(QueryFiledUtil.appendMin24(data.getTeachDate()));
//        Date date = DateUtil.getNowDatetime();
//        if (date.getTime() > teachDate.getTime()) {
//            return R.fail("活动日期：" + data.getTeachDate() + " 已过期，不能操作");
//        }

        // 获取员工在门店的角色权限
        StaffRoles staffRole = staffRolesService.getStoreUidAndStaffUid(storeUid, staffUid);
        if (null == staffRole || StringUtils.isBlank(staffRole.getRoles()))
            return R.fail("员工角色权限获取失败");
        if (!AccountUtil.isStoreManager(staffRole.getRoles())) {
            // 不是店长，是普通员工点名，判断主讲导读和日期
            if (!username.equals(lesson.getTeacherUid()))
                return R.fail("您不是本活动的主讲导读，不能操作");
            Date teachDate = DateUtil.parseDateFromStr(QueryFiledUtil.appendMin24(lesson.getTeachDate()));
            Date date = DateUtil.getNowDatetime();
            if (date.getTime() > teachDate.getTime()) {
                return R.fail("活动日期：" + lesson.getTeachDate() + " 已过期，不能操作");
            }
        }

        Page<CaClass> page = classService.getInsertCassV2(pageUtil, storeUid, lesson.getClassId(), lesson.getProjectUid(), lesson.getStageUid(), keyword);
        PageBeanDto dto = new PageBeanDto();
        dto.setTotal(page.getTotalRow());
        dto.setList(page.getRecords());
        return R.ok(dto);
    }

    @ApiOperation(value = "获取社团内可插班的会员列表")
    @PostMapping(value = "/getClassMembers", produces = "application/json; charset=UTF-8")
    public R<Object> getClassMembers(
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "活动uid") @RequestParam(value = "lessonUid") String lessonUid,
            @ApiParam(value = "社团id") @RequestParam(value = "classId") Long classId,
            @ApiParam(value = "姓名或手机号") @RequestParam(value = "keyword", required = false) String keyword
    ) throws Exception {
        CaScheduleLesson data = scheduleLessonService.getLessonInfo(storeUid, lessonUid);
        if (null == data) return R.fail("活动获取失败");
        if (data.getStatus().equals(-1)) return R.fail("活动已取消，不能操作");
        if (data.getStatus().equals(2)) return R.fail("活动已完成，不能操作");

        // 获取社团的会员信息
        List<CaClassMemberDto> classMembers = classMemberService.getClassMemberList(corpUid, storeUid, classId, data.getProjectUid(), keyword);
        // 设置已加入的会员状态
        if (CollectionUtils.isNotEmpty(classMembers)) {
            // 获取点名时的会员，本社团/插班/补缺/试听
            List<String> memberUidList = scheduleLessonService.getMemberUidByClassMemberAndCallMember(storeUid, data.getClassId(), lessonUid);

            for (CaClassMemberDto classMember : classMembers) {
                String memberUid = classMember.getMemberUid();
                classMember.setStudentTypeName("活动会员");
                if (memberUidList.contains(memberUid))
                    classMember.setAddStatus(1);
                else
                    classMember.setAddStatus(0);
            }
        }
        return R.ok(classMembers);
    }

    @ApiOperation(value = "获取可补缺的活动，根据服务项目查询")
    @PostMapping(value = "/getMakeUpLessons", produces = "application/json; charset=UTF-8")
    public R<Object> getMakeUpLessons(
            HttpServletRequest request,
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "分页公共类") PageUtil pageUtil,
            @ApiParam(value = "活动uid") @RequestParam(value = "lessonUid") String lessonUid,
            @ApiParam(value = "社团id") @RequestParam(value = "classId", required = false) Long classId,
            @ApiParam(value = "活动室id") @RequestParam(value = "roomId", required = false) Long roomId,
            @ApiParam(value = "教师username") @RequestParam(value = "username", required = false) String username,
            @ApiParam(value = "活动开始日期") @RequestParam(value = "beginDate", required = false) String beginDate,
            @ApiParam(value = "活动结束日期") @RequestParam(value = "endDate", required = false) String endDate
    ) throws Exception {
        // 获取员工信息
        R<Object> r = LoginInfoUtil.getLoginDto(request);
        if (R.isError(r)) return r;
        LoginDataDto loginDto = (LoginDataDto) r.getData();

        CaScheduleLesson lesson = scheduleLessonService.getLessonInfo(storeUid, lessonUid);
        if (null == lesson) return R.fail("活动获取失败");
        if (lesson.getStatus().equals(-1)) return R.fail("活动已取消，不能操作");
        if (lesson.getStatus().equals(2)) return R.fail("活动已结束，不能操作");
//        Date teachDate = DateUtil.parseDateFromStr(QueryFiledUtil.appendMin24(lesson.getTeachDate()));
//        Date date = DateUtil.getNowDatetime();
//        if (date.getTime() > teachDate.getTime()) {
//            return R.fail("活动日期：" + lesson.getTeachDate() + " 已过期，不能操作");
//        }
        // 获取员工在门店的角色权限
        StaffRoles staffRole = staffRolesService.getStoreUidAndStaffUid(storeUid, staffUid);
        if (null == staffRole || StringUtils.isBlank(staffRole.getRoles()))
            return R.fail("员工角色权限获取失败");
        if (!AccountUtil.isStoreManager(staffRole.getRoles())) {
            // 不是店长，是普通员工点名，判断主讲导读和日期
            if (!loginDto.getUsername().equals(lesson.getTeacherUid()))
                return R.fail("您不是本活动的主讲导读，不能操作");
            Date teachDate = DateUtil.parseDateFromStr(QueryFiledUtil.appendMin24(lesson.getTeachDate()));
            Date date = DateUtil.getNowDatetime();
            if (date.getTime() > teachDate.getTime()) {
                return R.fail("活动日期：" + lesson.getTeachDate() + " 已过期，不能操作");
            }
        }

        Page<CaScheduleLessonDto> page = scheduleLessonService.getMakeUpLessonsV2(pageUtil, storeUid, lessonUid,
                lesson.getProjectUid(), lesson.getStageUid(), classId, roomId, username, beginDate, endDate);
        PageBeanDto dto = new PageBeanDto();
        dto.setTotal(page.getTotalRow());
        dto.setList(page.getRecords());
        return R.ok(dto);
    }

    @ApiOperation(value = "获取可补缺的活动下的会员列表")
    @PostMapping(value = "/getMakeUpMembers", produces = "application/json; charset=UTF-8")
    public R<Object> getMakeUpMembers(
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "活动uid") @RequestParam(value = "lessonUid") String lessonUid,
            @ApiParam(value = "补缺活动id") @RequestParam(value = "makeupLessonUid") String makeupLessonUid
    ) {
        CaScheduleLesson lesson = scheduleLessonService.getLessonInfo(storeUid, lessonUid);
        if (null == lesson) return R.fail("活动获取失败");
        if (lesson.getStatus().equals(-1)) return R.fail("活动已取消，不能操作");
        if (lesson.getStatus().equals(2)) return R.fail("活动已结束，不能操作");

        CaScheduleLesson makeUpLesson = scheduleLessonService.getLessonInfo(storeUid, makeupLessonUid);
        if (null == makeUpLesson) return R.fail("补缺活动获取失败");
        if (makeUpLesson.getStatus().equals(-1)) return R.fail("补缺活动已取消，不能操作");
        if (makeUpLesson.getStatus().equals(0)) return R.fail("补缺活动未开始，不能操作");
        if (makeUpLesson.getStatus().equals(1)) return R.fail("补缺活动未完成，不能操作");

        // 获取补缺活动下的请假和未到会员
        List<CaCallNamesDto> callNamesList = callNameService.getNotReachAndAskLeaveMember(storeUid, makeUpLesson.getScheduleUid(), makeUpLesson.getLessonUid());

        if (CollectionUtils.isNotEmpty(callNamesList)) {
            // 获取补缺会员uid
            List<String> memberUids = callNamesList.stream().map(CaCallNamesDto::getMemberUid).collect(Collectors.toList());

            // 获取活动的会员，本社团/插班/补缺/试听
            List<String> memberUidList = scheduleLessonService.getMemberUidByClassMemberAndCallMember(storeUid, lesson.getClassId(), lessonUid);

            // 设置补缺会员的服务项目的剩余次数
            Map<String, LeftLessonDto> dtoMap = cmservicesService.getLeftLessonCntV2(storeUid, makeUpLesson.getProjectUid(), memberUids);

            for (CaCallNamesDto callNames : callNamesList) {
                String memberUid = callNames.getMemberUid();
                // 服务项目的剩余次数
                LeftLessonDto leftLessonDto = dtoMap.get(memberUid);
                if (leftLessonDto != null) {
                    callNames.setProductName(leftLessonDto.getProductName());
                    callNames.setTyProductName(leftLessonDto.getTyProductName());
                    callNames.setLeftLessonCnt(NepUtil.nullToZero(leftLessonDto.getLeftLessonCnt()));
                    callNames.setTyLeftLessonCnt(NepUtil.nullToZero(leftLessonDto.getTyLeftLessonCnt()));
                } else {
                    callNames.setProductName("");
                    callNames.setTyProductName("");
                    callNames.setLeftLessonCnt(0);
                    callNames.setTyLeftLessonCnt(0);
                }

                // 是否已经加入过活动
                if (memberUidList.contains(memberUid))
                    callNames.setAddStatus(1);
                else
                    callNames.setAddStatus(0);
            }
        }
        return R.ok(callNamesList);
    }

    @ApiOperation(value = "获取可试听的会员列表")
    @PostMapping(value = "/getAuditionMembers", produces = "application/json; charset=UTF-8")
    public R<Object> getAuditionMembers(
            HttpServletRequest request,
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "分页公共类") PageUtil pageUtil,
            @ApiParam(value = "活动uid") @RequestParam(value = "lessonUid") String lessonUid,
            @ApiParam(value = "姓名或手机号") @RequestParam(value = "keyword", required = false) String keyword
    ) throws Exception {
        // 获取员工信息
        R<Object> r = LoginInfoUtil.getLoginDto(request);
        if (R.isError(r)) return r;
        LoginDataDto loginDto = (LoginDataDto) r.getData();
        String username = loginDto.getUsername();

        CaScheduleLesson lesson = scheduleLessonService.getLessonInfo(storeUid, lessonUid);
        if (null == lesson) return R.fail("活动获取失败");
        if (lesson.getStatus().equals(-1)) return R.fail("活动已取消，不能操作");
        if (lesson.getStatus().equals(2)) return R.fail("活动已结束，不能操作");

        // 获取员工在门店的角色权限
        StaffRoles staffRole = staffRolesService.getStoreUidAndStaffUid(storeUid, staffUid);
        if (null == staffRole || StringUtils.isBlank(staffRole.getRoles()))
            return R.fail("员工角色权限获取失败");
        if (!AccountUtil.isStoreManager(staffRole.getRoles())) {
            // 不是店长，是普通员工点名，判断主讲导读和日期
            if (!username.equals(lesson.getTeacherUid()))
                return R.fail("您不是本活动的主讲导读，不能操作");
            Date teachDate = DateUtil.parseDateFromStr(QueryFiledUtil.appendMin24(lesson.getTeachDate()));
            Date date = DateUtil.getNowDatetime();
            if (date.getTime() > teachDate.getTime()) {
                return R.fail("活动日期：" + lesson.getTeachDate() + " 已过期，不能操作");
            }
        }

        PageDto<AddMemberDto> page = membersService.getAuditionMembers(pageUtil, corpUid, storeUid, keyword);
        long total = page.getTotal();
        List<AddMemberDto> list = page.getList();

        if (CollectionUtils.isNotEmpty(list)) {
            // 获取点名时的会员，本社团/插班/补缺/试听
            List<String> memberUidList = scheduleLessonService.getMemberUidByClassMemberAndCallMember(storeUid, lesson.getClassId(), lessonUid);

            for (AddMemberDto dto : list) {
                String memberUid = dto.getMemberUid();
                if (memberUidList.contains(memberUid))
                    dto.setAddStatus(1);
                else
                    dto.setAddStatus(0);
            }
        }
        PageBeanDto dto = new PageBeanDto();
        dto.setTotal(total);
        dto.setList(list);
        return R.ok(dto);
    }

    @ApiOperation(value = "活动添加会员（插班、补缺、试听）")
    @PostMapping(value = "/addTempMembers", produces = "application/json; charset=UTF-8")
    public R<Object> addTempMembers(
            HttpServletRequest request,
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "活动uid") @RequestParam(value = "lessonUid") String lessonUid,
            @ApiParam(value = "会员uid") @RequestParam(value = "memberUid") String memberUid,
            @ApiParam(value = "会员类型 1.本活动会员 2.补缺会员 3.插班会员 4.试听会员") @RequestParam(value = "studentType") Integer studentType,
            @ApiParam(value = "会员要补缺的活动uid") @RequestParam(value = "makeupLessonUid", required = false) String makeupLessonUid,
            @ApiParam(value = "备注") @RequestParam(value = "remark", required = false) String remark
    ) throws Exception {
        // 获取员工信息
        R<Object> r = LoginInfoUtil.getLoginDto(request);
        if (R.isError(r)) return r;
        LoginDataDto loginDto = (LoginDataDto) r.getData();
        long storeId = loginDto.getCurrentStoreId();

        CaScheduleLesson lesson = scheduleLessonService.getLessonInfo(storeUid, lessonUid);
        if (null == lesson)
            return R.fail("没有查询到活动");
        if (lesson.getStatus().equals(-1))
            return R.fail("活动已取消，不能操作");
        if (lesson.getStatus().equals(2))
            return R.fail("活动已结束，不能操作");
//        Date teachDate = DateUtil.parseDateFromStr(QueryFiledUtil.appendMin24(lesson.getTeachDate()));
//        Date date = DateUtil.getNowDatetime();
//        if (date.getTime() > teachDate.getTime())
//            return R.fail("活动日期：" + lesson.getTeachDate() + " 已过期，不能添加");
        // 获取员工在门店的角色权限
        StaffRoles staffRole = staffRolesService.getStoreUidAndStaffUid(loginDto.getCurrentStoreUid(), loginDto.getStaffUid());
        if (null == staffRole || StringUtils.isBlank(staffRole.getRoles()))
            return R.fail("员工角色权限获取失败");
        if (!AccountUtil.isStoreManager(staffRole.getRoles())) {
            // 不是店长，是普通员工点名，判断主讲导读和日期
            if (!loginDto.getUsername().equals(lesson.getTeacherUid()))
                return R.fail("您不是本活动的主讲导读，不能操作");
            Date teachDate = DateUtil.parseDateFromStr(QueryFiledUtil.appendMin24(lesson.getTeachDate()));
            Date date = DateUtil.getNowDatetime();
            if (date.getTime() > teachDate.getTime()) {
                return R.fail("活动日期：" + lesson.getTeachDate() + " 已过期，不能操作");
            }
        }

        // 最新的主讲导读姓名
        Staff staff = staffService.getByUsername(lesson.getTeacherUid());
        if (staff == null)
            return R.fail("未查询到主讲导读");
        String teacherName = staff.getFullName();

        Members members = membersService.getByUid(storeUid, memberUid);
        if (null == members)
            return R.fail("没有查询到会员");
        if (!members.getEnabled().equals(1))
            return R.fail("会员已被禁用");

        // 社团里的会员
        if (lesson.getClassId() != null) {
            String uid = classMemberService.getByClassIdAndMemberUid(storeUid, lesson.getClassId(), memberUid);
            if (StringUtils.isNotBlank(uid))
                return R.fail("会员已在该活动的社团 " + lesson.getClassName() + " 内");
        }

        // 插班、补缺、试听的会员
        String studentTypeName = callNameService.getTempMembers(storeUid, lessonUid, memberUid);
        if (StringUtils.isNotBlank(studentTypeName))
            return R.fail("会员已加入该活动，会员类型：" + studentTypeName);

        Date time = DateUtil.getNowDatetime();

        if (studentType.equals(2)) {
            // 如果是补缺
            if (StringUtils.isBlank(makeupLessonUid))
                return R.fail("补缺活动id不能为空");
            boolean l = callNameService.updateMemberMakeUp(storeUid, makeupLessonUid, lessonUid, memberUid);
            if (!l)
                return R.fail("会员的点名记录状态改为已补失败");
        } else if (studentType.equals(4)) {
            // 如果是试听，则获取会员当月的试听次数
            long auditionCnt = callNameService.getMemberMonthAuditionCnt(storeUid, memberUid);
            if (auditionCnt >= 3)
                return R.fail("该会员当月的试听数不能超过3次");

            String followType = EnumType.Follow.AUDITION.getType();
            String followTypeName = EnumType.Follow.AUDITION.getName();
            //TODO 创建跟进记录
            MemberFollow follow = FollowUtil.newFollow(corpUid, storeUid, storeName, staffUid, loginDto.getFullName(),
                    members.getUid(), members.getMemberName(), followType, followTypeName,
                    "添加试听，服务：" + lesson.getProductName() + "，导读：" + lesson.getTeacherName() +
                            ",时间：" + lesson.getTeachDate() + " " + lesson.getBeginTime() + "-" + lesson.getEndTime(),
                    lessonUid, time);
            memberFollowService.saveOrUpdate(follow);
            // 更新会员的最后跟进信息
            membersService.updateLastFollowInfo(storeUid, memberUid, follow.getUid(), time);
        }

        // 创建点名记录
        CaCallNames data = ScheduleUtil.newCallName(null, lesson, corpUid, storeUid, storeName, staffUid, staffName,
                teacherName, members.getId(), members.getUid(), members.getMemberName(), members.getMob(),
                studentType, null, null, 0, null, remark);
        callNameService.saveOrUpdate(data);

        // 更新活动下的插班、补缺、试听的会员数量
        long num = callNameService.getTempMemberNum(storeUid, lessonUid);
        int studentTempNum = Math.toIntExact(num);
        scheduleLessonService.updateStudentTempNum(storeUid, lessonUid, studentTempNum);

        return R.ok();
    }

    @ApiOperation(value = "删除活动下会员的点名记录（插班、补缺、试听）")
    @PostMapping(value = "/dropTempMembers", produces = "application/json; charset=UTF-8")
    public R<Object> dropTempMembers(
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "活动uid") @RequestParam(value = "lessonUid") String lessonUid,
            @ApiParam(value = "会员uid") @RequestParam(value = "memberUid") String memberUid
    ) {
        CaScheduleLesson lesson = scheduleLessonService.getLessonInfo(storeUid, lessonUid);
        if (null == lesson) return R.fail("活动获取失败");
        if (lesson.getStatus().equals(-1)) return R.fail("活动已取消，不能操作");
        if (lesson.getStatus().equals(2)) return R.fail("活动已结束，不能操作");

        // 查找插班、补缺、试听会员已有的点名记录
        CaCallNames data = callNameService.getTempCallName(storeUid, lessonUid, memberUid);
        if (null == data)
            return R.fail("会员的插班/补缺的点名记录不存在");

        long l = callNameService.dropBean(storeUid, lessonUid, data.getId());
        if (l <= 0) return R.failDel();

        // 更新活动下的插班、补缺、试听的会员数量
        long studentTempNum = callNameService.getTempMemberNum(storeUid, lessonUid);
        int num = Math.toIntExact(studentTempNum);
        scheduleLessonService.updateStudentTempNum(storeUid, lessonUid, num);

        // 判断点名记录是补缺会员，则更新补缺会员的点名记录为未补缺
        if (data.getStudentType().equals(2)) {
            callNameService.dropMemberMakeUp(storeUid, lessonUid, data.getMemberUid());
        }

        return R.ok();
    }

    @ApiOperation(value = "活动点名时获取会员")
    @PostMapping(value = "/getCallMembers", produces = "application/json; charset=UTF-8")
    public R<Object> getCallMembers(
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "活动uid") @RequestParam(value = "lessonUid") String lessonUid
    ) throws Exception {
        CaScheduleLesson lesson = scheduleLessonService.getLessonInfo(storeUid, lessonUid);
        if (null == lesson) return R.fail("活动获取失败");
        if (lesson.getStatus().equals(-1)) return R.fail("活动已取消，不能操作");
        if (lesson.getStatus().equals(2)) return R.fail("活动已结束，不能操作");

        int studentNum = NepUtil.nullToZero(lesson.getStudentNum()) + NepUtil.nullToZero(lesson.getStudentTempNum());

        List<CallMemberDto> members = new ArrayList<>();
        if (studentNum > 0) {
            String lessonStoreUid = lesson.getStoreUid();
            // 获取点名时的会员，本社团/插班/补缺/试听
            members = scheduleLessonService.getClassMemberAndCallMember(lessonStoreUid, lesson.getClassId(), lessonUid);
            // 获取会员对应服务的剩余次数
            if (CollectionUtils.isNotEmpty(members)) {
                List<String> memberUids = members.stream().map(CallMemberDto::getMemberUid).distinct().collect(Collectors.toList());

                List<String> zeroMemberUids = new ArrayList<>();
                // 设置会员的服务项目的剩余次数
                Map<String, LeftLessonDto> dtoMap = cmservicesService.getLeftLessonCntV2(storeUid, lesson.getProjectUid(), memberUids);
                for (CallMemberDto dto : members) {
                    LeftLessonDto leftLessonDto = dtoMap.get(dto.getMemberUid());
                    if (leftLessonDto != null) {
                        dto.setProductName(leftLessonDto.getProductName());
                        dto.setTyProductName(leftLessonDto.getTyProductName());
                        int leftLessonCnt = NepUtil.nullToZero(leftLessonDto.getLeftLessonCnt());
                        dto.setLeftLessonCnt(leftLessonCnt);
                        int tyLeftLessonCnt = NepUtil.nullToZero(leftLessonDto.getTyLeftLessonCnt());
                        dto.setTyLeftLessonCnt(tyLeftLessonCnt);

                        if (leftLessonCnt <= 0 && tyLeftLessonCnt <= 0)
                            zeroMemberUids.add(dto.getMemberUid());
                    } else {
                        dto.setProductName(lesson.getProductName());
                        dto.setTyProductName("体验课");
                        dto.setLeftLessonCnt(0);
                        dto.setTyLeftLessonCnt(0);

                        zeroMemberUids.add(dto.getMemberUid());
                    }
                }

                // 课次数量不足的会员检查是否有未开卡的服务
                if (CollectionUtils.isNotEmpty(zeroMemberUids)) {
                    String beginDate = DateUtil.getNowDateStr();
                    for (String memberUid : zeroMemberUids) {
                        // 查询课次大于0、未结课、未开卡、不收激活费用的服务
                        Cmservices service = cmservicesService.getMemberConsumesNoCardService(storeUid, memberUid, lesson.getProjectUid());
                        if (service != null) {
                            for (CallMemberDto dto : members) {
                                if (dto.getMemberUid().equals(memberUid))
                                    dto.setLeftLessonCnt(service.getTotalLessons());
                            }

                            Date beginDateValue = DateUtil.parseDate(beginDate);
                            // 计算结束日期
                            Date endDateValue = DateUtil.addDays(beginDateValue, service.getServiceDays());
                            // 设置服务开卡
                            cmservicesService.setStatusV3(
                                    storeUid, service.getOrderCode(), service.getUid(), staffUid, staffName,
                                    beginDateValue, endDateValue, null,
                                    EnumType.ServiceStatus.OPEN_CARD.getStatus(), EnumType.ServiceStatus.OPEN_CARD.getName()
                            );
                        }
                    }
                }
            }
        }
        return R.ok(members);
    }

    @ApiOperation(value = "判断是否能设置已完成")
    @PostMapping(value = "/judgeFinish", produces = "application/json; charset=UTF-8")
    public R<Object> judgeFinish(
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "活动uid") @RequestParam(value = "lessonUid") String lessonUid
    ) {
        CaScheduleLesson lesson = scheduleLessonService.getLessonInfo(storeUid, lessonUid);
        if (null == lesson) return R.fail("活动获取失败");
        if (lesson.getStatus().equals(-1)) return R.fail("活动已取消，不能操作");
        if (lesson.getStatus().equals(0)) return R.fail("活动还未点名，不能操作");
        if (lesson.getStatus().equals(2)) return R.fail("活动已完成，不能操作");

        String lessonStoreUid = lesson.getStoreUid();

        // 获取点名时的会员，本社团/插班/补缺/试听
        List<CallMemberDto> members = scheduleLessonService.getClassMemberAndCallMember(lessonStoreUid, lesson.getClassId(), lessonUid);

        Set<String> memberUids = new HashSet<>();
        for (CallMemberDto dto : members) {
            String memberUid = dto.getMemberUid();
            String memberName = dto.getMemberName();
            Integer callStatus = dto.getCallStatus();
            if (StringUtils.isBlank(memberUid) || null == callStatus || callStatus.equals(0))
                return R.fail("发现未被点名的会员：" + memberName + "，不能操作");
            if (memberUids.contains(memberUid))
                return R.fail("发现重复的会员：" + memberName + "，不能操作");
            memberUids.add(memberUid);
        }

        return R.ok();
    }

    @Transactional
    @ApiOperation(value = "活动状态设置为已完成（扣除课时）")
    @PostMapping(value = "/setFinish", produces = "application/json; charset=UTF-8")
    public R<Object> setFinish(
            HttpServletRequest request,
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "活动uid") @RequestParam(value = "lessonUid") String lessonUid
    ) throws Exception {
        // 获取员工信息
        R<Object> r = LoginInfoUtil.getLoginDto(request);
        if (R.isError(r)) return r;
        LoginDataDto loginDto = (LoginDataDto) r.getData();
        Integer operationType = loginDto.getCurrentOperationType();

        CaScheduleLesson lesson = scheduleLessonService.getLessonInfo(storeUid, lessonUid);
        if (null == lesson) return R.fail("活动获取失败");
        if (lesson.getStatus().equals(-1)) return R.fail("活动已取消，不能操作");
        if (lesson.getStatus().equals(0)) return R.fail("活动还未点名，不能操作");
        if (lesson.getStatus().equals(2)) return R.fail("活动已完成，不能操作");

        Date closeTime = DateUtil.getNowDatetime();
        String lessonStoreUid = lesson.getStoreUid();
        Integer freeStatus = lesson.getFreeStatus();
        String beginTime = lesson.getTeachDate() + " " + lesson.getBeginTime() + " ~ " + lesson.getEndTime();

        // 获取活动下的点名记录
        List<CaCallNames> callNamesList = callNameService.listByStoreUidAndLessonUid(lessonStoreUid, lessonUid);
        if (CollectionUtils.isNotEmpty(callNamesList)) {
            Map<String, Cmservices> servicesMap = new HashMap<>();
            // 收费
            if (freeStatus.equals(1)) {
                // 获取会员可消耗剩余活动的服务项目列表(会员是到课/迟到且非试听)
                List<String> memberUidList = callNamesList.stream()
                        .filter(callName ->
                                null != callName.getCallStatus() && !callName.getStudentType().equals(4) && !callName.getCallStatus().equals(0) &&
                                        (callName.getCallStatus().equals(1) || callName.getCallStatus().equals(2))
                        )
                        .map(CaCallNames::getMemberUid)
                        .collect(Collectors.toList());

                List<String> errorList = new ArrayList<>();
                if (CollectionUtils.isNotEmpty(memberUidList)) {
                    // 第二版、按订单创建时间升序且赠送升序查可消耗的服务
                    for (CaCallNames callName : callNamesList) {
                        if (null != callName.getCallStatus() && !callName.getStudentType().equals(4) && !callName.getCallStatus().equals(0) &&
                                (callName.getCallStatus().equals(1) || callName.getCallStatus().equals(2))
                        ) {
                            Cmservices cmservices = cmservicesService.getMemberConsumesService(
                                    lessonStoreUid, callName.getMemberUid(), lesson.getProjectUid()
                            );

                            if (null != cmservices && StringUtils.isBlank(cmservices.getOrderType()))
                                errorList.add(cmservices.getMemberName() + "," + cmservices.getOrderCode());
                            servicesMap.put(callName.getMemberUid(), cmservices);
                        }
                    }
                }
                if (CollectionUtils.isNotEmpty(errorList)) {
                    return R.fail("请去维护会员订单的收入类型" + String.join("；", errorList));
                }
            }

            boolean l = scheduleLessonService.setOk(lessonStoreUid, lessonUid, staffUid, staffName, closeTime);
            if (!l)
                return R.fail("设置已完成失败");

            ArrayList<String> memberUidsForPush = new ArrayList<>();
            if (freeStatus.equals(1)) {
                // 收费课，点名记录设置完成
                List<Long> noHourCallId = new ArrayList<>();
                for (CaCallNames callName : callNamesList) {
                    Cmservices cmservices = servicesMap.get(callName.getMemberUid());
                    // 会员类型 1.本活动会员 2.补缺会员 3.插班会员 4.试听会员
                    if (null != cmservices && !callName.getStudentType().equals(4) && (callName.getCallStatus().equals(1) || callName.getCallStatus().equals(2))) {
                        // 扣课时的会员：到课、迟到、非试听会员
                        // 消耗一次服务项目的剩余活动数量，会员是到课/迟到且不是试听且服务项目有课时可扣
                        l = cmservicesService.updateLeftLesson(corpUid, lessonStoreUid, callName.getMemberUid(), cmservices.getUid());
                        if (!l)
                            throw new Exception("消耗服务项目的剩余活动数量失败会员姓名：" + callName.getMemberName());

                        // 获取课时消耗的类型
                        CallHourDto callHourDto = ScheduleUtil.getHourType(
                                freeStatus, callName.getCallStatus(), callName.getStudentType(),
                                cmservices.getOrderType(), cmservices.getUid(), cmservices.getIsGift()
                        );
                        // 点名记录设置为已结束，并关联消耗的服务项目信息
                        l = callNameService.setCallOk(
                                corpUid, lessonStoreUid, lessonUid, callName.getId(), cmservices.getOrderCode(),
                                cmservices.getUid(), cmservices.getOrderType(), cmservices.getIsGift(), NepUtil.nullToZero(cmservices.getUnitAmount()),
                                callHourDto.getHourType(), callHourDto.getHourTypeName(), staffUid, staffName, closeTime
                        );
                        if (!l)
                            throw new Exception("点名记录关联消耗的服务项目失败会员姓名：" + callName.getMemberName());
                        if (!ScheduleUtil.TIYAN_UID.equals(cmservices.getProjectUid())) {
                            memberUidsForPush.add(cmservices.getMemberUid());
                        }
                    } else {
                        // 未扣课时的会员：请假、未到、试听、活动次数不足、服务项目剩余次数不足
                        noHourCallId.add(callName.getId());
                    }
                }

                // 微信公众号会员剩余次数推送
                boolean pashStatus = storeFunctionService.getDegreeStatus(storeUid, EnumFunction.FunctionInfo.PUSH_FUNC.getIdentify());
                if (pashStatus) {
                    if (CollectionUtils.isNotEmpty(memberUidsForPush)) {
                        String tokenData = WxGzhUtil.getWxAccessToken();
                        List<Cmservices> cmservicesList = cmservicesService.getPushCmservices(corpUid, storeUid, lesson.getProjectUid(), memberUidsForPush);
                        wxTemplateUtil.wxSendToRelatives(cmservicesList, tokenData, beginTime);
                    }
                }

                // 收费课未扣课时，点名记录设置完成
                if (CollectionUtils.isNotEmpty(noHourCallId))
                    callNameService.setOkAnNoHour(corpUid, lessonStoreUid, lessonUid, noHourCallId, staffUid, staffName, closeTime);

            } else {
                // 免费课，点名记录设置完成
                callNameService.setFreeOk(corpUid, lessonStoreUid, lessonUid, staffUid, staffName, closeTime);
            }
        }
        return R.ok();
    }

    @ApiOperation(value = "查询已完成活动的点名详情")
    @PostMapping(value = "/getOkLessons", produces = "application/json; charset=UTF-8")
    public R<Object> getOkLessons(
            HttpServletRequest request,
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "分页公共类") PageUtil pageUtil,
            @ApiParam(value = "社团名称") @RequestParam(value = "className", required = false) String className,
            @ApiParam(value = "活动服务uid") @RequestParam(value = "projectUid", required = false) String projectUid,
            @ApiParam(value = "服务阶段uid") @RequestParam(value = "stageUid", required = false) String stageUid,
            @ApiParam(value = "活动室id") @RequestParam(value = "roomId", required = false) Long roomId,
            @ApiParam(value = "主讲导读username") @RequestParam(value = "teacherUid", required = false) String teacherUid,
            @ApiParam(value = "开始日期") @RequestParam(value = "beginDate", required = false) String beginDate,
            @ApiParam(value = "结束日期") @RequestParam(value = "endDate", required = false) String endDate
    ) {
        R<Object> r = LoginInfoUtil.getLoginDto(request);
        if (R.isError(r)) return r;
        LoginDataDto loginDto = (LoginDataDto) r.getData();

        String username = loginDto.getUsername();
        StaffRoleDto roleDto = AccountUtil.getStaffRole(loginDto.getStoreRoles());
        if (null == roleDto)
            return R.fail("未发现员工的角色权限");

        int staffRole = roleDto.getRole();

        Page<CaScheduleLessonDto> page = scheduleLessonService.getOkLessonDtoPageV3(
                pageUtil, null, storeUid, className, projectUid, stageUid, roomId, teacherUid, beginDate, endDate,
                staffRole, username
        );
        long total = page.getTotalRow();
        List<CaScheduleLessonDto> lessons = page.getRecords();

        if (CollectionUtils.isNotEmpty(lessons)) {
            List<String> lessonUidList = lessons.stream().map(CaScheduleLessonDto::getLessonUid).collect(Collectors.toList());
            // 获取课次的点名统计
            Map<String, Map<String, Long>> lessonHourMap = callNameService.hourList(lessonUidList);
            if (lessonHourMap != null) {
                for (CaScheduleLessonDto lesson : lessons) {
                    // 课时消耗类型统计
                    Map<String, Long> hourMap = lessonHourMap.get(lesson.getLessonUid());
                    JSONArray hourTypes = new JSONArray();
                    if (hourMap != null) {
                        hourTypes = setHourTypes(hourMap);
                    }
                    lesson.setHourTypes(hourTypes);
                }
            }
        }

        PageBeanDto dto = new PageBeanDto();
        dto.setTotal(total);
        dto.setList(lessons);
        return R.ok(dto);
    }

    @ApiOperation(value = "快速创建活动-获取会员列表")
    @PostMapping(value = "/getAddMembers", produces = "application/json; charset=UTF-8")
    public R<Object> getAddMembers(
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "分页公共类") PageUtil pageUtil,
            @ApiParam(value = "服务uid") @RequestParam(value = "projectUid") String projectUid,
            @ApiParam(value = "会员姓名") @RequestParam(value = "fullName", required = false) String fullName,
            @ApiParam(value = "年级") @RequestParam(value = "grade", required = false) Integer grade,
            @ApiParam(value = "导读员工uid") @RequestParam(value = "readStaffUid", required = false) String readStaffUid
    ) {
        StoreProjects data = storeProjectsService.getByUid(projectUid);
        if (data == null)
            return R.fail("服务项目获取失败");
        if (!data.getEnabled().equals(1))
            return R.fail("服务项目已被禁用");

        PageDto<AddMemberDto> page = null;
        if (data.getFreeStatus() != null && data.getFreeStatus().equals(0)) {
            // 免费社团，查试听会员
            page = membersService.getByServiceMembers(pageUtil, corpUid, storeUid, fullName, grade, readStaffUid);
        } else {
            // 收费社团，查服务项目的会员
            page = membersService.serviceMemberList(pageUtil, corpUid, storeUid, fullName, grade, projectUid, readStaffUid);
        }

        return R.ok(page);
    }


    @ApiOperation(value = "导出活动记录")
    @PostMapping(value = "/exportList", produces = "application/vnd.ms-excel;charset=UTF-8")
    public void exportList(
            HttpServletResponse response,
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "社团名称") @RequestParam(value = "className", required = false) String className,
            @ApiParam(value = "活动服务uid") @RequestParam(value = "projectUid", required = false) String projectUid,
            @ApiParam(value = "服务阶段uid") @RequestParam(value = "stageUid", required = false) String stageUid,
            @ApiParam(value = "活动室id") @RequestParam(value = "roomId", required = false) Long roomId,
            @ApiParam(value = "主讲导读username") @RequestParam(value = "teacherUid", required = false) String teacherUid,
            @ApiParam(value = "开始日期") @RequestParam(value = "beginDate", required = false) String beginDate,
            @ApiParam(value = "结束日期") @RequestParam(value = "endDate", required = false) String endDate
    ) throws Exception {
        //  获取本月的第一天和最后一天
        if (StringUtils.isBlank(className) && StringUtils.isBlank(projectUid) && StringUtils.isBlank(stageUid)
                && StringUtils.isBlank(teacherUid) && roomId == null
                && (StringUtils.isBlank(beginDate) || StringUtils.isBlank(endDate))
        ) {
            Date monthMinDate = DateUtil.getMonthMinDate();
            Date monthMaxDate = DateUtil.getMonthMaxDate();
            beginDate = DateUtil.getDefaultTime2DateStr(monthMinDate);
            endDate = DateUtil.getDefaultTime2DateStr(monthMaxDate);
        }

        List<CaScheduleLesson> lessons = scheduleLessonService.getOkLessonsV3(
                storeUid, className, projectUid, stageUid, roomId, teacherUid, beginDate, endDate, null
        );

        List<LessonVO> voList = new ArrayList<>();

        int firstStartRow = 1;
        int firstEndRow = 0;
        // 需要合并的行号
        List<RowBean> firstRows = new ArrayList<>();
        // 需要合并的列号
        List<Integer> firstColumns = Lists.newArrayList(0, 1);

        if (CollectionUtils.isNotEmpty(lessons)) {
            List<String> lessonUids = lessons.stream().map(CaScheduleLesson::getLessonUid).collect(Collectors.toList());

            // 获取课时消耗统计
            List<CaCallNamesDto> callNamesList = callNameService.listByLessonUidIn(lessonUids);
            Map<List<Object>, Long> groupingMap = new HashMap<>();
            if (CollectionUtils.isNotEmpty(callNamesList)) {
                //  定义一个函数Function，该函数将元素对象映射到一个键的集合里
                Function<CaCallNamesDto, List<Object>> compositeKey =
                        callNames -> Arrays.asList(callNames.getLessonUid(), callNames.getHourType());
                // 多字段分组
                groupingMap = callNamesList.stream().collect(Collectors.groupingBy(compositeKey, Collectors.counting()));
            }

            Map<String, List<CaScheduleLesson>> lessonMap = lessons.stream().collect(Collectors.groupingBy(CaScheduleLesson::getTeacherUid));
            for (Map.Entry<String, List<CaScheduleLesson>> entry : lessonMap.entrySet()) {
                String teacherUidValue = entry.getKey();
                List<CaScheduleLesson> lessonList = entry.getValue();
                int lessonNum = lessonList.size();

                firstEndRow += lessonNum;
                // 合并必须包含2个或更多单元格
                if (firstStartRow != firstEndRow)
                    firstRows.add(new RowBean(firstStartRow, firstEndRow));
                firstStartRow += lessonNum;

                for (CaScheduleLesson lesson : lessonList) {
                    LessonVO lessonVO = new LessonVO();
                    lessonVO.setLessonNum(lessonNum);
                    lessonVO.setStoreName(lesson.getStoreName());
                    lessonVO.setTeachDate(lesson.getTeachDate() + " " + lesson.getBeginTime() + "-" + lesson.getEndTime());
                    lessonVO.setWeekName(lesson.getWeekName());
                    lessonVO.setClassName(lesson.getClassName());
                    lessonVO.setProductName(lesson.getProductName());
                    lessonVO.setStageName(lesson.getStageName());
                    lessonVO.setRoomName(lesson.getRoomName());
                    lessonVO.setTeacherName(lesson.getTeacherName());
                    lessonVO.setStudentNum(lesson.getStudentNum() + lesson.getStudentTempNum());
                    lessonVO.setReachNum(lesson.getReachNum() + lesson.getLateNum() + lesson.getNoHourNum());
                    lessonVO.setNotReachNum(lesson.getAskLeaveNum() + lesson.getNotReachNum());
                    lessonVO.setCloseStaffName(lesson.getCloseStaffName());
                    if (null != lesson.getCloseTime())
                        lessonVO.setCloseTime(DateUtil.getDefaultTimeStr(lesson.getCloseTime()));

                    // 课时消耗类型统计
                    lessonVO.setPayNum(NepUtil.nullToZero(groupingMap.get(Arrays.asList(lesson.getLessonUid(), 1))));
                    lessonVO.setGiftNum(NepUtil.nullToZero(groupingMap.get(Arrays.asList(lesson.getLessonUid(), 2))));
                    lessonVO.setExpNum(NepUtil.nullToZero(groupingMap.get(Arrays.asList(lesson.getLessonUid(), 3))));
                    lessonVO.setAuditionNum(NepUtil.nullToZero(groupingMap.get(Arrays.asList(lesson.getLessonUid(), 4))));
                    lessonVO.setFreeNum(NepUtil.nullToZero(groupingMap.get(Arrays.asList(lesson.getLessonUid(), 0))));
                    lessonVO.setNoHourNum(NepUtil.nullToZero(groupingMap.get(Arrays.asList(lesson.getLessonUid(), -1))));

                    // 加入导出列表
                    voList.add(lessonVO);
                }
            }
        }

        String fileName = "活动记录" + beginDate + "至" + endDate;
        ExcelHandler.exportMergeExcel(response, voList, LessonVO.class, fileName, "活动记录", firstRows, firstColumns);
    }

    @ApiOperation(value = "导出活动统计")
    @PostMapping(value = "/exportBillList", produces = "application/vnd.ms-excel;charset=UTF-8")
    public void exportBillList(
            HttpServletResponse response,
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "社团名称") @RequestParam(value = "className", required = false) String className,
            @ApiParam(value = "活动服务uid") @RequestParam(value = "projectUid", required = false) String projectUid,
            @ApiParam(value = "服务阶段uid") @RequestParam(value = "stageUid", required = false) String stageUid,
            @ApiParam(value = "活动室id") @RequestParam(value = "roomId", required = false) Long roomId,
            @ApiParam(value = "主讲导读username") @RequestParam(value = "teacherUid", required = false) String teacherUid,
            @ApiParam(value = "开始日期") @RequestParam(value = "beginDate", required = false) String beginDate,
            @ApiParam(value = "结束日期") @RequestParam(value = "endDate", required = false) String endDate
    ) throws Exception {
        //  获取本月的第一天和最后一天
        if (StringUtils.isBlank(className) && StringUtils.isBlank(projectUid) && StringUtils.isBlank(stageUid)
                && StringUtils.isBlank(teacherUid) && roomId == null
                && (StringUtils.isBlank(beginDate) || StringUtils.isBlank(endDate))
        ) {
            Date monthMinDate = DateUtil.getMonthMinDate();
            Date monthMaxDate = DateUtil.getMonthMaxDate();
            beginDate = DateUtil.getDefaultTime2DateStr(monthMinDate);
            endDate = DateUtil.getDefaultTime2DateStr(monthMaxDate);
        }

        List<CaScheduleLesson> lessons = scheduleLessonService.getOkLessonsV3(
                storeUid, className, projectUid, stageUid, roomId, teacherUid, beginDate, endDate, null
        );

        List<LessonBillVO> voList = new ArrayList<>();

        if (CollectionUtils.isNotEmpty(lessons)) {
            List<String> lessonUids = lessons.stream().map(CaScheduleLesson::getLessonUid).collect(Collectors.toList());
            // 获取课时消耗统计
            List<CaCallNamesDto> callNamesList = callNameService.listByLessonUidIn(lessonUids);
            Map<List<Object>, Long> groupingMap = new HashMap<>();
            if (CollectionUtils.isNotEmpty(callNamesList)) {
                //  定义一个函数Function，该函数将元素对象映射到一个键的集合里
                Function<CaCallNamesDto, List<Object>> compositeKey =
                        callNames -> Arrays.asList(callNames.getLessonUid(), callNames.getHourType());
                // 多字段分组
                groupingMap = callNamesList.stream().collect(Collectors.groupingBy(compositeKey, Collectors.counting()));
            }

            List<String> hourTypeList = Lists.newArrayList("未扣", "免费", "正价", "赠送", "体验", "试听");
            for (CaScheduleLesson lesson : lessons) {
                // 课时消耗类型统计
                for (int i = 0; i < hourTypeList.size(); i++) {
                    LessonBillVO billVO = new LessonBillVO();
                    billVO.setStoreName(lesson.getStoreName());
                    billVO.setTeachDate(lesson.getTeachDate() + " " + lesson.getBeginTime() + "-" + lesson.getEndTime());
                    billVO.setWeekName(lesson.getWeekName());
                    billVO.setClassName(lesson.getClassName());
                    billVO.setProductName(lesson.getProductName());
                    billVO.setStageName(lesson.getStageName());
                    billVO.setRoomName(lesson.getRoomName());
                    billVO.setTeacherName(lesson.getTeacherName());
                    billVO.setStudentNum(lesson.getStudentNum() + lesson.getStudentTempNum());
                    billVO.setReachNum(lesson.getReachNum() + lesson.getLateNum() + lesson.getNoHourNum());
                    billVO.setNotReachNum(lesson.getAskLeaveNum() + lesson.getNotReachNum());
                    billVO.setCloseStaffName(lesson.getCloseStaffName());
                    billVO.setCloseTime(DateUtil.getDefaultTimeStr(lesson.getCloseTime()));
                    billVO.setHourType(hourTypeList.get(i));

                    // 设置单个单元格多种样式
                    WriteCellData<String> richTest = new WriteCellData<>();
                    richTest.setType(CellDataTypeEnum.RICH_TEXT_STRING);
                    billVO.setHourNum(richTest);
                    RichTextStringData richTextStringData = new RichTextStringData();
                    richTest.setRichTextStringDataValue(richTextStringData);

                    // 字体样式
                    WriteFont writeFont = new WriteFont();
                    // 字体大小
                    writeFont.setFontHeightInPoints((short) 14);
                    short fontColor = IndexedColors.GREEN.getIndex();
                    if (i == 0 || i == 1 || i == 5) {
                        fontColor = IndexedColors.RED.getIndex();
                    }
                    long hourNum = NepUtil.nullToZero(groupingMap.get(Arrays.asList(lesson.getLessonUid(), i - 1)));
                    // 字体颜色
                    writeFont.setColor(fontColor);
                    richTextStringData.setTextString(hourNum + "");
                    richTextStringData.applyFont(writeFont);

                    // 加入导出列表
                    voList.add(billVO);
                }
            }
        }
        String fileName = "活动统计" + beginDate + "至" + endDate;
        ExcelHandler.exportExcel(response, voList, LessonBillVO.class, fileName, "活动统计", true);
    }

    /**
     * 系统点名完成后，统计课时消耗
     */
    private JSONArray setHourTypes(Map<String, Long> hourTypeMap) {
        JSONArray array = new JSONArray();
        for (Map.Entry<String, Long> entry : hourTypeMap.entrySet()) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("hourType", entry.getKey());
            jsonObject.put("num", entry.getValue());
            array.add(jsonObject);
        }
        return array;
    }

}